/*
 * Copyright (c) 2009 Nathaniel Houghton <nathan@brainwerk.org>
 *                    Robert Kirchgessner <rkirchge@gmail.com>
 *
 * Permission to use, copy, modify, and distribute this software for
 * any purpose with or without fee is hereby granted, provided that
 * the above copyright notice and this permission notice appear in all
 * copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA
 * OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 * PERFORMANCE OF THIS SOFTWARE.
 *
 */

#include <ctype.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>

#include "lcd.h"
#include "util.h"
#include "usart.h"

/* this thing is crap, but it's not called often... */
uint32_t
byte_swap(uint32_t bits)
{
	uint8_t *in, *out;
	uint32_t ret;

	in = (uint8_t *) &bits;
	out = (uint8_t *) &ret;

	out[0] = in[3];
	out[1] = in[2];
	out[2] = in[1];
	out[3] = in[0];

	return ret;
}

void
fatal(char *str)
{
	cli();
	lcd_clrscr();
	lcd_home(0);
	lcd_print("Terminated:");
	lcd_home(1);
	lcd_print("  ");
	lcd_print(str);

	for (;;);
}

uint32_t
hexstr(char *buf, uint8_t len)
{
	uint32_t n;
	uint32_t digit = 0;
	int pow;
	int i;

	n = 0;
	pow = len - 1;
	while (*buf && pow >= 0) {
		char c = toupper(*buf);
		if (c >= '0' && c <= '9')
			digit = c - '0';
		else if (c >= 'A' && c <= 'F')
			digit = c - 'A' + 10;
		else
			fatal("invalid hex digit.");

		for (i = pow; i; --i)
			digit *= 16;

		n += digit;
		++buf;
		--pow;
	}

	if (*buf == '\0' && pow >= 0)
		fatal("hexstr string too short.");

	return n;
}

void
hexdump(void *buf, uint16_t len)
{
	char str[4];
	uint16_t i;
	uint8_t *p;

	p = buf;

	for (i = 0; i < len; ++i) {
		sprintf(str, "%02x ", *p);
		usart_puts(0, str);
		++p;
	}

	usart_puts(0, "\r\n");
}

void *
xmalloc(size_t n)
{
	void *r;

	r = malloc(n);

	if (r == NULL)
		fatal("Malloc failure.");

	return r;
}
